/**
 * Foxit Software Inc.
 * Copyright(C) 2005-2014, all rights reserved.
 * The following code is copyrighted and contains proprietary information
 * and trade secrets of Foxit Software Inc.

 * Description: PageViewManager
 * Author: shaojie zhuo
 * Update: shaojie zhuo (2014-05-13 11:44)
 */

define(function (require, exports, module) {
    require('../ViewLevel.js');
    var Config = WebPDF.Config;

    /**
     * page range
     * @param startIndex Start index of page.
     * @param endIndex End index of page.
     * @constructor
     */
    var PageRange = function (startIndex, endIndex) {
        this.startIndex = startIndex;
        this.endIndex = endIndex;
    };
    WebPDF.PDFView.PageRange = PageRange;

    /**
     * 步进式加载 viewer 相关的处理类
     * @param docView Doc view
     * @param viewerContainerId Id of viewer container.
     * @constructor
     * @ignore
     */
    var ProgressiveViewerGenerator = function(docView){
       var _docView = docView,          
        /**
         * 用于步进式页面创建，存储已经创建的页面列表，数组中每个对象为PageRange类型;
         * @type {Array.<WebPDF.PDFView.PageRange>}
         * @private
         */
            _createdPageArray = [],
            _self = this;
        /**
         * Check whether a page has been created.
         * @param pageIndex Page index to check.
         * @returns {boolean} Return true if the page has been created, otherwise return false.
         * @private
         */
        function _isPageCreated(pageIndex) {
            for (var i = 0; i < _createdPageArray.length; i++) {
                var pageRange = _createdPageArray[i];
                if (pageRange.startIndex <= pageIndex && pageRange.endIndex >= pageIndex)
                    return true;
            }
            return false;
        }

        /**
         * 获取已经创建内容的页面索引列表
         * @returns {Array.<Number>}
         * @private
         */
        this.getContentCreatedPageIndexList = function() {
            var k = 0;
            var pageIndexList = [];
            var pageCnt = _docView.getPageCount();
            for (var i=0; i<pageCnt; i++) {
                if (_docView.getPageView(i).isContentCreated()) {
                    pageIndexList[k] = i;
                    k++;
                }
            }
            return pageIndexList;
        };

        /**
         * 根据页面索引，获取当前已经创建的，并且在对应页面之前，同时最接近对应页面的页面索引;
         * @param pageIndex 页面索引
         * @returns {number}
         * @private
         */
        function _getPageIndexToInsert(pageIndex) {
            var pageIndexToInsert = -1;
            var minDistance = pageIndex;
            for (var i = 0; i < _createdPageArray.length; i++) {
                var pageRange = _createdPageArray[i];
                var tmpDistance = pageIndex - pageRange.endIndex;
                if (tmpDistance > 0 && tmpDistance < minDistance) {
                    minDistance = tmpDistance;
                    pageIndexToInsert = pageRange.endIndex;
                }
            }
            return pageIndexToInsert;
        }

        /**
         * 根据页面索引，获取需要创建的页面区间;
         * @param pageIndex
         * @returns {PageRange}
         * @private
         */
        function _getPageRangeToCreate(pageIndex) {
            var maxPage2Create = Config.defaults.maxNewPagesPerTime;
            //为-1, 表示创建所有页面;
            if (maxPage2Create === -1) {
                maxPage2Create = _docView.getPageCount();
            }
            var startIndex = parseInt(pageIndex / maxPage2Create) * maxPage2Create;
            return new PageRange(startIndex, startIndex + maxPage2Create - 1);
        }

        /**
         * 根据给出的页面索引创建指定范围内的Page View
         * @param pageIndex
         * @returns {*}
         */
        this.createPages = function(pageIndex) {
            var pageCnt = _docView.getPageCount();
            if (pageIndex<0 || pageIndex>=pageCnt) {
                return false;
            }
            if (_isPageCreated(pageIndex)) {
                return false;
            }
            var pageRangeToCreate = _getPageRangeToCreate(pageIndex);
            if (pageRangeToCreate.startIndex < 0) {
                pageRangeToCreate.startIndex = 0;
            }
            if (pageRangeToCreate.endIndex >= pageCnt) {
                pageRangeToCreate.endIndex = pageCnt - 1;
            }
            var pageIndexToInsert = _getPageIndexToInsert(pageRangeToCreate.startIndex);
            _createdPageArray.push(pageRangeToCreate);
            return _docView.createPagesView(pageRangeToCreate.startIndex, pageRangeToCreate.endIndex, pageIndexToInsert);
        };

        /**
         * 创建指定页面相邻的页面
         * @param curPageIndex
         * @param offsetY
         */
        this.createAdjacentPage = function(curPageIndex, offsetY) {
            var pageCount = _docView.getPageCount();
            var range = _self.countVisiblePageRange();
            var lastVisiblePageIndex = range.end;
            var firstVisiblePageIndex = range.begin;
            var scrollApi = _docView.getScrollApi();
            if (scrollApi) {
                var isDocViewChanged = false;
                if (firstVisiblePageIndex>=1 && !_docView.getPageView(firstVisiblePageIndex - 1).isContentCreated()) {
                    isDocViewChanged = _self.createPages(firstVisiblePageIndex - 1);
                }
                if (lastVisiblePageIndex<pageCount-1 && !_docView.getPageView(lastVisiblePageIndex + 1).isContentCreated()) {
                    isDocViewChanged |= _self.createPages(lastVisiblePageIndex + 1);
                }
                if (isDocViewChanged) {
                    var offsetX = scrollApi.getContentPositionX();
                    //重新计算显示范围
                    range = _self.countVisiblePageRange();
                    lastVisiblePageIndex = range.end;
                    firstVisiblePageIndex = range.begin;
                    _self.progressiveUpdatePageDimension(curPageIndex, firstVisiblePageIndex, lastVisiblePageIndex,
                        offsetY, true, false);
                    _docView.reinitializeScrollBar();
                    var pageDomElem = document.getElementById(_docView.getPageView(curPageIndex).getPageViewContainerID());
                    scrollApi.scrollToElement(pageDomElem, true, false, offsetY);
                    scrollApi.scrollToX(offsetX);
                    //继续创建直到超出当前可视区域;
                    _self.createAdjacentPage(curPageIndex, offsetY);
                    _docView.reinitializeScrollBar();
                    scrollApi.scrollToElement(pageDomElem, true, false, offsetY);
                    scrollApi.scrollToX(offsetX);
                }
            }
        };

        /**
         * 根据当前放大倍数，步进式修改页面大小
         * @param {Number} pageIndex 步进式处理后，要跳转到的页面索引
         * @param {Number} startVisibleIndex 处于显示区域的第一页页面索引
         * @param {Number} endVisibleIndex 处于显示区域的最后一页页面索引
         * @param {Number} offsetY 第一个参数指定页面相对于当前显示区域的y轴偏移量
         * @param {Boolean} isScrollX 是否滚动X轴
         * @param {Boolean} isResizeScroll 是否重新计算滚动条
         */
        this.progressiveUpdatePageDimension = function (pageIndex, startVisibleIndex, endVisibleIndex,
                                                        offsetY, isScrollX, isResizeScroll) {
            var pageCount = _docView.getPageCount();
            var isPageDimensionChanged = false;
            var resizePageCountPerTime = Config.defaults.maxResizePagesPerTime;
            //为-1代表所有页面
            if (resizePageCountPerTime === -1) {
                resizePageCountPerTime = _docView.getPageCount();
            }
            var startPageIndex = startVisibleIndex - resizePageCountPerTime > 0 ? startVisibleIndex - resizePageCountPerTime : 0;
            var endPageIndex = endVisibleIndex + resizePageCountPerTime;
            if (endPageIndex >= pageCount) {
                endPageIndex = pageCount - 1;
            }
            var pageView;
            for (var i = startPageIndex; i <= endPageIndex; i++) {
                pageView = _docView.getPageView(i);
                if (!pageView.isContentCreated() || pageView.isDimensionUpdated()) {
                    continue;
                }
                pageView.updateDimension();
                pageView.setScale(_docView.getScale());
                pageView.setDimensionUpdated(true);
                isPageDimensionChanged = true;
            }

            if (isPageDimensionChanged && isResizeScroll) {
                var scrollApi = _docView.getScrollApi();
                if (scrollApi) {
                    _docView.reinitializeScrollBar();
                    var offsetX = scrollApi.getContentPositionX();
                    pageView = _docView.getPageView(pageIndex);
                    var pageContainerElem = pageView.el;
                    scrollApi.scrollToElement(pageContainerElem, true, false, offsetY);
                    isScrollX && scrollApi.scrollToX(offsetX);
                }
                else {
                    _docView.reinitializeScrollBar();
                }
                return true;
            }
            else {
                return false;
            }
        };

        /**
         * Count visible page range.
         * @returns {{begin: number, current: number, end:number}}
         */
        this.countVisiblePageRange = function () {
            var range = {begin: 0, current: 0, end: 1};
            var createPageIndexList = _self.getContentCreatedPageIndexList();
            var createdPageCount = createPageIndexList.length;
            var left = 0;
            var right = createdPageCount - 1;
            var mid = (left + right) >> 1;
            var jqPagesContainerDiv = _docView.$el;
            /*if(WebPDF.Environment.mobile){
                jqPagesContainerDiv = jqPagesContainerDiv.parent();
            }*/
            var contentPanelHeight = jqPagesContainerDiv.height();
            var contentPanelOffset = jqPagesContainerDiv.offset();
            var pageView, jqPage, pos, height, pageTop;
            while (mid > left) {
                pageView = _docView.getPageView(createPageIndexList[mid]);
                jqPage = pageView.$el;
                pos = jqPage.offset();
                height = pageView.getPageViewHeight();
                pageTop = pos.top;
                if ((pageTop <= contentPanelOffset.top) && (pageTop + height <= contentPanelOffset.top)) {
                    left = mid + 1;
                    mid = (left + right) >> 1;
                } else if ((pageTop > (contentPanelOffset.top + contentPanelHeight))) {
                    right = mid - 1;
                    mid = (left + right) >> 1;
                } else {
                    break;
                }
            }

            range.begin = createPageIndexList[mid];
            range.end = range.begin;
            var i;
            for (i = mid; i >= 0; i--) {
                pageView = _docView.getPageView(createPageIndexList[i]);
                jqPage = pageView.$el;
                pos = jqPage.offset();
                height = pageView.getPageViewHeight();
                pageTop = pos.top;
                if (pageTop + height > contentPanelOffset.top) {
                    range.begin = createPageIndexList[i];
                } else {
                    if (i == mid && mid < createdPageCount - 1) {  //mid页面不可见
                        mid += 1;
                        range.begin = createPageIndexList[mid];
                    }
                    break;
                }
            }

            range.current = range.begin;
            range.end = createPageIndexList[mid];
            for (i = mid + 1; i < createdPageCount; i++) {
                pageView = _docView.getPageView(createPageIndexList[i]);
                jqPage = pageView.$el;
                pos = jqPage.offset();
                pageTop = pos.top;
                if (pageTop < contentPanelHeight + contentPanelOffset.top) {
                    range.end = createPageIndexList[i];
                } else {
                    break;
                }
            }
            for (i = range.begin; i <= range.end; i++) {
                pageView = _docView.getPageView(i);
                if (!pageView.isContentCreated()) {
                    range.begin = i + 1;
                }
            }
            for (i = range.begin; i <= range.end; i++) {
                pageView = _docView.getPageView(i);
                if (!pageView.isContentCreated()) {
                    continue;
                }
                jqPage = pageView.$el;
                height = pageView.getPageViewHeight();
                pos = jqPage.offset();
                pageTop = pos.top;
                if (((pageTop >= contentPanelOffset.top) && (pageTop < contentPanelOffset.top + contentPanelHeight)
                    && (pageTop + height / 3 <= contentPanelOffset.top + contentPanelHeight))
                    || ((pageTop <= contentPanelOffset.top) && (pageTop + height >= contentPanelOffset.top + contentPanelHeight * 2 / 3))) {
                    range.current = i;
                    break;
                }
            }
            return range;
        };
    };

    module.exports = ProgressiveViewerGenerator;
});